package com.test.auth_db_auto.config;

import com.test.auth_db_auto.auth_sms.SmsAuthenticationProvider;
import com.test.auth_db_auto.auth_sms.SmsSecurityConfig;
import com.test.auth_db_auto.filter.BootPictureCodeAuthenticationFilter;
import com.test.auth_db_auto.handler.BootLoginFailureHandler;
import com.test.auth_db_auto.support.AuthenticationProviderImpl;
import com.test.auth_db_auto.support.BootSecurityProperties;
import com.test.auth_db_auto.support.MyUserDetailsService;
import com.test.auth_db_auto.support.code.BootCodeService;
import com.test.auth_db_auto.support.properities.BootBaseLoginProperties;
import com.test.auth_db_auto.support.properities.BootSmsLoginProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * Spring Security配置类
 *   资源服务
 * @ Author: .Mr
 * @ ClassName SecurityConfig
 * @ Description TODO
 * @ date 2021/12/20 10:26
 * @ Version 1.0
 */
@Configuration
@EnableWebSecurity
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    private MyUserDetailsService myUserDetailsService;
    private BootLoginFailureHandler handler;
    private BootSecurityProperties properties;
    private BootPictureCodeAuthenticationFilter pictureCodeAuthenticationFilter;
    private SmsSecurityConfig smsSecurityConfig;  //短信登录的校验框架

    public SecurityConfig(MyUserDetailsService myUserDetailsService, BootLoginFailureHandler handler,
                          BootSecurityProperties properties, BootCodeService<String> codeService,
                          SmsSecurityConfig smsSecurityConfig){
        this.myUserDetailsService=myUserDetailsService;
        this.handler=handler;
        this.properties=properties;
        this.pictureCodeAuthenticationFilter=new BootPictureCodeAuthenticationFilter(properties,codeService,handler);
        this.smsSecurityConfig=smsSecurityConfig;
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth){
        auth.authenticationProvider(daoAuthenticationProvider());
    }

    @Bean
    public AuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider impl = new AuthenticationProviderImpl(myUserDetailsService);
        impl.setUserDetailsService(myUserDetailsService);
        impl.setHideUserNotFoundExceptions(false) ;

        return impl ;
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
//        return new BCryptPasswordEncoder();
    }

/*    public static void main(String[] args) {
        //用户密码
        String password = "11";
        //密码加密
        BCryptPasswordEncoder passwordEncoder=new BCryptPasswordEncoder();
        //加密
        String newPassword = passwordEncoder.encode(password);
        System.out.println("------------->>>>"+newPassword);
        //$2a$10$spcpx7OEXrKQ6fpslUaolu3gr5rPxxSlt/41J4Iuco2nImvfTumPu

       *//* boolean matches = passwordEncoder.matches(password, "$2a$10$06S5v7Mo47e8Qyv65Ltz.uhcQwfhIcgYDKVPVzBlPj6UHWV2ErbzK");
        System.out.println(matches);*//*
    }*/

    @Override
    public void configure(WebSecurity web) throws Exception {
        //解决静态资源被拦截的问题
        web.ignoring().antMatchers(properties.getCodePath(),"/asserts/**","favicon.ico", "/statics/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        BootBaseLoginProperties base=properties.getBaseLogin();   // 基础登录的配置
        BootSmsLoginProperties sms = properties.getSmsLogin();    // 短信登录的配置

        http
                // http security 要拦截的url，这里这拦截，oauth2相关和登录登录相关的url，其他的交给资源服务处理
                .requestMatchers()
                .antMatchers("/oauth/**","/token/revoke",base.getLoginProcessUrl(),properties.getLoginPage(),sms.getLoginProcessUrl())
                .and()
                .authorizeRequests()
                // 自定义页面或处理url是，如果不配置全局允许，浏览器会提示服务器将页面转发多次
                .antMatchers("/oauth/**",base.getLoginProcessUrl(),properties.getLoginPage(),sms.getLoginProcessUrl())
                .permitAll()
                .anyRequest()
                .authenticated();

        http.formLogin()
                .failureHandler(handler)
                /*
                *  // 请求 {用户名} 参数名称
                .usernameParameter(base.getUsernameParameterName())
                // 请求 {密码} 参数名
                .passwordParameter(base.getPasswordParameterName())
                * */
                .loginPage(properties.getLoginPage())  //自定义登录页面
                .loginProcessingUrl(base.getLoginProcessUrl());  //自定义表单处理url

        http.httpBasic().disable();
        //手机号短信登录的
        http.apply(this.smsSecurityConfig);
        // 用户密码验证之前校验验证码
        http.addFilterBefore(pictureCodeAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    public SmsAuthenticationProvider smsAuthenticationProvider(){return new SmsAuthenticationProvider();}
}
